"""
通义万相（DashScope）图像生成提供商（简化实现）

说明：
- 若未配置有效 apiKey，则使用占位服务 placehold.co 生成 PNG 占位图，保证流程可用。
- 若配置了 apiKey，将尝试调用 DashScope 同步接口；失败将回退到占位图。
"""
from typing import Dict, Any, Optional
from loguru import logger

from storyforge.providers.base import ProviderBase
from storyforge.utils.http_client import HTTPClient


class ImageWanxiangProvider(ProviderBase):
    """通义万相图像生成（简化版）"""

    def __init__(self, config: Dict[str, Any]):
        super().__init__(config)
        from storyforge.config import get_config

        self.api_key: Optional[str] = config.get("apiKey")
        self.base_url: str = config.get(
            "base_url",
            config.get("endpoint", "https://dashscope.aliyuncs.com/api/v1/services/aigc/text2image/image-synthesis")
        )
        self.model: str = config.get("model", "wanx-v1")
        self.extra: Dict[str, Any] = config.get("extra", {}) or {}

        global_config = get_config()
        timeout = getattr(global_config.llm, "requestTimeout", 60)
        self.http = HTTPClient({"timeout": timeout, "maxRetries": 2})

    def name(self) -> str:
        return "wanxiang"

    def _use_placeholder(self) -> bool:
        return not self.api_key or str(self.api_key).startswith("YOUR_")

    def submit(self, payload: Dict[str, Any]) -> str:
        """
        提交生成任务（同步场景下直接返回 job_id）
        payload 需要包含：prompt, width, height, style（可选）, seed（可选）
        """
        import time
        job_id = f"wanx_{int(time.time()*1000)}"

        prompt: str = payload.get("prompt", "")
        width: int = int(payload.get("width", 1024))
        height: int = int(payload.get("height", 1024))
        style: str = payload.get("style") or self.extra.get("style") or "<auto>"
        seed: Optional[int] = payload.get("seed")  # 新增：接收 seed 参数
        character_name: Optional[str] = payload.get("character_name")  # 新增：用于占位图

        if self._use_placeholder():
            # 不调用外部接口，后续 poll 返回占位图 URL
            self._ensure_store()
            # 在占位图 URL 中包含角色名称以便区分
            placeholder_text = character_name if character_name else "ref"
            self._results[job_id] = {
                "status": "succeeded",
                "result_url": f"https://placehold.co/{width}x{height}.png?text={placeholder_text}",
                "error": None,
                "is_placeholder": True  # 标记为占位图
            }
            if character_name:
                logger.warning(f"未配置有效的通义万相 apiKey，为角色 '{character_name}' 使用占位图")
            else:
                logger.warning("未配置有效的通义万相 apiKey，使用占位图生成以保证流程可用")
            return job_id

        # 调用 DashScope（失败时回退占位图）
        try:
            headers = {
                "Authorization": f"Bearer {self.api_key}",
                "Content-Type": "application/json",
                "X-DashScope-Async": "enable"
            }
            # 适配 DashScope 文档的典型请求体（简化）
            body = {
                "model": self.model,
                "input": {
                    "prompt": prompt
                },
                "parameters": {
                    "size": f"{width}*{height}",
                    "style": style
                }
            }
            
            # 新增：如果提供了 seed，添加到 parameters 中
            if seed is not None:
                body["parameters"]["seed"] = seed
                logger.debug(f"使用固定 seed: {seed}")
            # 使用 base_url 作为完整 endpoint
            resp = self.http.post(self.base_url, headers=headers, json_data=body, timeout=(15, 60))
            if resp.status_code not in (200, 202):
                raise Exception(f"DashScope返回错误: {resp.status_code} {resp.text}")
            data = resp.json()

            # 异步：提取 task_id，交由 poll 查询
            task_id = None
            if isinstance(data, dict):
                # 可能为 {"output":{"task_id": "..."}}
                out = data.get("output") or data.get("data") or data
                if isinstance(out, dict):
                    task_id = out.get("task_id") or out.get("id") or out.get("taskId")
            if not task_id:
                # 有些账号可能仍返回同步结果（含 url），做一次直接解析
                result_url = self._try_extract_result_url(data)
                if result_url:
                    self._ensure_store()
                    self._results[job_id] = {"status": "succeeded", "result_url": result_url, "error": None}
                    logger.info("通义万相图像生成成功（同步返回）")
                    return job_id
                raise Exception(f"未找到task_id/图片URL: {data}")

            # 记录任务
            self._ensure_store()
            self._jobs[job_id] = task_id
            self._results[job_id] = {"status": "running", "result_url": None, "error": None}
            logger.info(f"通义万相图像任务已提交，task_id={task_id}")
            return job_id
        except Exception as e:
            logger.error(f"通义万相调用失败，将回退到占位图: {e}")
            self._ensure_store()
            placeholder_text = character_name if character_name else "ref"
            self._results[job_id] = {
                "status": "succeeded",
                "result_url": f"https://placehold.co/{width}x{height}.png?text={placeholder_text}",
                "error": None,
                "is_placeholder": True
            }
            return job_id

    def poll(self, external_job_id: str) -> Dict[str, Any]:
        """
        查询任务状态；当为异步任务时，调用 DashScope tasks 接口
        """
        self._ensure_store()
        # 如果已经有结果，直接返回
        if external_job_id in self._results and self._results[external_job_id]["status"] == "succeeded":
            return self._results[external_job_id]

        task_id = self._jobs.get(external_job_id)
        if not task_id:
            # 无法定位任务，返回失败
            return {"status": "failed", "result_url": None, "error": "Unknown job id"}

        # 调用 tasks 查询状态
        try:
            import requests
            url = f"https://dashscope.aliyuncs.com/api/v1/tasks/{task_id}"
            headers = {"Authorization": f"Bearer {self.api_key}"}
            resp = requests.get(url, headers=headers, timeout=30)
            if resp.status_code != 200:
                return {"status": "running", "result_url": None, "error": f"query {resp.status_code}"}
            data = resp.json()

            # 状态解析（兼容不同字段）
            status = None
            out = data.get("output") or data.get("data") or data
            if isinstance(out, dict):
                status = out.get("task_status") or out.get("status") or out.get("state") or data.get("task_status")

            # 统一状态判定
            status_upper = str(status or "").upper()
            if status_upper in ("SUCCEEDED", "SUCCESS", "SUCCEED", "FINISHED", "DONE"):
                result_url = self._try_extract_result_url(data)
                if result_url:
                    self._results[external_job_id] = {"status": "succeeded", "result_url": result_url, "error": None}
                    return self._results[external_job_id]
                # 成功但未解析到URL
                return {"status": "succeeded", "result_url": None, "error": "no url in response"}
            elif status_upper in ("FAILED", "ERROR"):
                return {"status": "failed", "result_url": None, "error": str(data)}
            else:
                # 仍在运行
                return {"status": "running", "result_url": None, "error": None}
        except Exception as e:
            return {"status": "running", "result_url": None, "error": str(e)}

    def _try_extract_result_url(self, data: Dict[str, Any]) -> Optional[str]:
        """尽力从多种返回结构中解析图片URL"""
        try:
            for key in ("output", "data", "result"):
                if key in data:
                    val = data[key]
                    # 可能是 dict 包含 images/results/files
                    if isinstance(val, dict):
                        if "images" in val and isinstance(val["images"], list) and val["images"]:
                            return val["images"][0].get("url")
                        if "results" in val and isinstance(val["results"], list) and val["results"]:
                            # 结果中可能是 {"url": "..."} 或 {"files":[{"url": "..."}]}
                            first = val["results"][0]
                            if isinstance(first, dict):
                                if "url" in first:
                                    return first.get("url")
                                files = first.get("files")
                                if isinstance(files, list) and files:
                                    return files[0].get("url")
                    if isinstance(val, list) and val and isinstance(val[0], dict):
                        if "url" in val[0]:
                            return val[0].get("url")
            # 顶层兜底
            return data.get("url") or data.get("image_url")
        except Exception:
            return None

    def _ensure_store(self):
        if not hasattr(self, "_jobs"):
            self._jobs: Dict[str, str] = {}
        if not hasattr(self, "_results"):
            self._results: Dict[str, Dict[str, Any]] = {}
